﻿using AliIotAmqpWorker.Common;
using IServices;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading;
using YL.Core.Entity;
using System.Linq;

namespace AliIotAmqpWorker
{
    public class DeviceDataTask: BaseTaskProvider
    {
        private readonly DeviceAlarmService deviceAlarmService;
        private readonly DeviceDataService deviceDataService;
        private Dictionary<string, int> AlarmDic=new Dictionary<string, int>();//报警记录
        private readonly IMeter_DeviceInfoServices deviceInfoServices;
        private readonly MongoDBHelper _mongoDBHelper;
        private DateTime lastDatetime = DateTime.Now;
        private MongoDbTag mongoDbTimeTag;
        private string dataworkerKey= "raw_data";

        public DeviceDataTask(DeviceDataService DeviceDataServices,
                              IMeter_DeviceDataHistoryServices DeviceDataHistoryServices,
                              IMeter_ClientInfoServices ClientInfoServices,
                              DeviceAlarmService alarmService,
                              IMeter_DeviceFailureDetailServices DeviceFailureDetailServices,
                              IMeter_DeviceInfoServices DeviceInfoServices,
                              MongoDBHelper mongoDBHelper)
        {
            deviceDataService = DeviceDataServices;  
            deviceInfoServices = DeviceInfoServices;
            deviceAlarmService = alarmService;
            _mongoDBHelper = mongoDBHelper;
        }
        /// <summary>
        /// 加载初始化时间参数
        /// </summary>
        private void LoadInitialTime()
        {
            var filterBuilder = Builders<MongoDbTag>.Filter;
            var filter = filterBuilder.And(filterBuilder.Eq(x => x.device_name, GlobalSetting.ClientCode),
                                           filterBuilder.Eq(x => x.value, dataworkerKey));
            var list = _mongoDBHelper.GetList<MongoDbTag>(GlobalSetting.MongoDbTime, filter);
            if(list !=null && list.Count>0)
            {
                mongoDbTimeTag = list[0];
                lastDatetime = mongoDbTimeTag.ts;
            }
            else
            {
                mongoDbTimeTag = new MongoDbTag();
                mongoDbTimeTag.device_name = GlobalSetting.ClientCode;
                mongoDbTimeTag.value = dataworkerKey;
                _mongoDBHelper.InsertOne<MongoDbTag>(mongoDbTimeTag, GlobalSetting.MongoDbTime);
                list = _mongoDBHelper.GetList<MongoDbTag>(GlobalSetting.MongoDbTime, filter);
                if (list != null && list.Count > 0)
                {
                    mongoDbTimeTag = list[0];
                }
            }
        }

        /// <summary>
        /// 启动任务
        /// </summary>
        public void StartTask()
        {
            thread = new Thread(TaskCycleHandle);
            thread.Start();
        }
        /// <summary>
        /// 任务周期循环处理
        /// </summary>
        public override void TaskCycleHandle()
        {
            DateTime dateTimeNow = DateTime.Now;
            AliIotDeviceData<ECU1151Info> deviceData;

            LoadInitialTime();//加载初始化时间参数
            Thread.Sleep(2000);
            Console.WriteLine($"read time is {lastDatetime}");
            while (true)
            {
                dateTimeNow = DateTime.Now;
                var filterBuilder = Builders<MongoDbTag>.Filter;
                var filter = filterBuilder.And(filterBuilder.Gt(x => x.ts, lastDatetime),
                                               filterBuilder.Lte(x => x.ts, dateTimeNow));
                var list = _mongoDBHelper.GetList<MongoDbTag>(dataworkerKey, filter);

                if (list != null && list.Count > 0)
                {
                    List<MongoDbTag> Tags = list.OrderBy(x => x.ts).ToList();
                    lastDatetime = Tags[Tags.Count - 1].ts;//获取最新时间
                    foreach (var item in Tags)
                    {
                        deviceData = Newtonsoft.Json.JsonConvert.DeserializeObject<AliIotDeviceData<ECU1151Info>>(item.value.ToString());
                        if (deviceData == null)
                        {
                            Thread.Sleep(500);
                            continue;
                        }
                        DeviceInfo device = deviceInfoServices.QueryableToEntity(x => x.AliDeviceName == deviceData.deviceName);
                        if (device == null )
                        {
                            continue;
                        }
                        Console.WriteLine($"-----处理设备数据：{device.AliDeviceName},gmtCreate={deviceData.gmtCreate}");
                        
                        deviceDataService.UpdateDeviceData(deviceData, device);//更新设备的参数
                    }
                    Tags.Clear();
                    Tags = null;
                }
                filterBuilder = Builders<MongoDbTag>.Filter;
                filter = filterBuilder.Lte(x => x.ts, dateTimeNow.AddDays(-7));//删除一周以前数据
                int count = _mongoDBHelper.DeleteMany(dataworkerKey, filter);
                UpdateCycleTime();//更新时间
                list = null;
                Thread.Sleep(5000);
            }
        }
        private Mutex mutex = new Mutex();
        /// <summary>
        /// 检测标识的下降沿。即报警，异常从1变为0时，需要更新结束时间
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool ChecFlagFaillingEdge(Dictionary<string, int> dic, string key,int value)
        {
            mutex.WaitOne();
            if (dic.ContainsKey(key))
            {
                if(dic[key]== value)
                {
                    return false;
                }
                else if (value == 0)//不相等，且变为0了
                {
                    return true;
                }
            }
            else
            {
                dic.Add(key, value);
                if(value==0)
                {
                    return true;
                }
            }
            mutex.ReleaseMutex();
            return false;
        }
        /// <summary>
        /// 增加记录
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        private void AddFlag(Dictionary<string, int> dic, string key, int value)
        {
            mutex.WaitOne();
            if (dic.ContainsKey(key)==false)
            {
                dic.Add(key, value);
            }
            mutex.ReleaseMutex();
        }
        /// <summary>
        /// 程序退出，存储最新时间记录
        /// </summary>
        public override void Dispose()
        {
            base.Dispose();
            UpdateCycleTime();
        }
        /// <summary>
        /// 更新存储时间
        /// </summary>
        public void UpdateCycleTime()
        {
            var filterBuilder = Builders<MongoDbTag>.Filter;
            var filter = filterBuilder.And(filterBuilder.Eq(x => x.device_name, GlobalSetting.ClientCode),
                                           filterBuilder.Eq(x => x.value, dataworkerKey));

            int count = _mongoDBHelper.DeleteMany<MongoDbTag>(GlobalSetting.MongoDbTime, filter);
            if (count > 0)
            {
                mongoDbTimeTag.ts = lastDatetime;
                _mongoDBHelper.InsertOne<MongoDbTag>(mongoDbTimeTag, GlobalSetting.MongoDbTime);
            }
        }
    }
}
